package com.jshan.blog.scheduled;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.jshan.blog.admin.service.LogRpcService;
import com.jshan.blog.base.admin.entity.SysOperationLog;
import com.jshan.blog.constans.QueueConst;
import com.jshan.blog.utils.RedisUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class LogConsumerService {

    @DubboReference
    private LogRpcService logRpcService;
    @Resource
    private RedisUtil redisUtil;


    @Scheduled(fixedRate = 5000) // 每5秒执行一次
    public void processLogQueue(){
        List<SysOperationLog> logList = new ArrayList<>(10); // 使用局部变量存储本次任务处理的日志
        while(true){
            String logJson = redisUtil.rPop(QueueConst.LOG_QUEUE_KEY);
            if(StringUtils.isBlank(logJson)){
                break; // 如果队列为空，推出循环
            }
            try {
                SysOperationLog logInfo = JSON.parseObject(logJson, new TypeReference<SysOperationLog>() {});

                logList.add(logInfo);

                // 当累积到10条时批量保存
                if (logList.size() >= 10) {
                    if (saveLogsAndHandleFailure(logList)) {
                        logList.clear(); // 保存成功，清空列表
                    } else {
                        break; // 保存失败，退出循环避免后续处理
                    }
                }
                // if (logRpcService.saveLog(logInfo)){
                //     log.info("日志处理成功：{}", logInfo);
                // }
            } catch (Exception e) {
                log.error("处理日志时发生错误", e);
                // 将解析失败的日志移入死信队列
                redisUtil.lPush(QueueConst.LOG_DEAD_QUEUE_KEY, logJson);
            }
        }
        // 处理剩余日志（不足10条）
        if (!logList.isEmpty()) {
            saveLogsAndHandleFailure(logList);
        }
    }
    /**
     * 批量保存日志并处理失败情况
     *
     * @param logs 待保存的日志列表
     * @return 是否保存成功
     */
    private boolean saveLogsAndHandleFailure(List<SysOperationLog> logs) {
        boolean success = logRpcService.saveLogs(logs);
        if (success) {
            log.info("日志批量保存成功，数量：{}", logs.size());
            return true;
        } else {
            log.error("日志批量保存失败，将重新放回队列头部");
            // 逆序放回以保持原处理顺序
            for (int i = logs.size() - 1; i >= 0; i--) {
                redisUtil.lPush(QueueConst.LOG_QUEUE_KEY, JSON.toJSONString(logs.get(i)));
            }
            return false;
        }
    }

}
